package org.maxgroundstation.simulation.service;

import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ServiceCommunicationUDP {

	// Default UDP port.
	private static final int DEFAULT_PORT = 10002;
	
	// Data members
	private ServiceCommunication comm;
	private ServiceSenderUDP sender;
	private ServiceReceiverUDP receiver;
    private DatagramSocket socket;
    private int port;
    private List<UDPClient> clients;
    
    /**
     * Constructor
     * @param comm the service communication.
     */
	ServiceCommunicationUDP(ServiceCommunication comm) {
		this.comm = comm;
		port = DEFAULT_PORT;
		sender = new ServiceSenderUDP(this);
		receiver = new ServiceReceiverUDP(this);
		clients = new ArrayList<UDPClient>();
		socket = null;
	}
	
    /**
     * Gets the service communication.
     * @return service communication.
     */
    ServiceCommunication getServiceCommunication() {
    	return comm;
    }
    
    /**
     * Gets the current port number.
     * @return port number.
     */
    public int getPort() {
        return port;
    }
    
    /**
     * Sets the port number.
     * @param port the new port number.
     */
    public void setPort(int port) {
        this.port = port;
    }
    
    /**
     * Connect to the socket.
     * @throws IOException if error connecting to socket.
     */
    public void connect() throws IOException {
        if (!isConnected()) {
        	InetAddress address = InetAddress.getByName(comm.getIPAddress());
            if ((socket == null) || socket.isClosed()) socket = new DatagramSocket(port, address);
            
            System.out.println("Connecting UDP service on port: " + port);
            //socket.connect(address, port);
            
            receiver.start();
        }
    }
    
    /**
     * Disconnect UDP connection from the socket.
     * @throws IOException if error disconnecting from socket.
     */
    public void disconnect() throws IOException {
        if (isConnected()) {
        	//comm.log("Disconnecting UDP service socket");
            socket.close();
            
            clients.clear();
        }
    }
    
    /**
     * Checks if connected to socket.
     * @return true if connected
     */
    public boolean isConnected() {
        return (socket != null) && !socket.isClosed();
    }
    
    /**
     * Gets the datagram socket.
     * @return the datagram socket.
     */
    public DatagramSocket getSocket() {
    	return socket;
    }
    
    boolean hasClient(String clientID) {
    	boolean result = false;
    	
    	Iterator<UDPClient> i = clients.iterator();
    	while (i.hasNext()) {
    		UDPClient client = i.next();
    		if (clientID.trim().equals(client.getClientID().trim())) result = true;
    	}
    	
    	return result;
    }
    
    UDPClient getClient(String clientID) {
    	UDPClient result = null;
    	
    	Iterator<UDPClient> i = clients.iterator();
    	while (i.hasNext()) {
    		UDPClient client = i.next();
    		if (clientID.trim().equals(client.getClientID().trim())) result = client;
    	}
    	
    	return result;
    }
    
    void addClient(String clientID, InetAddress address, int port) {
    	if (!hasClient(clientID)) clients.add(new UDPClient(clientID, address, port));
    }
    
    public void sendServicePost(String serviceID, String clientID, byte[] data) throws Exception {
    	sender.sendServicePost(serviceID, clientID, data);
    }
}